
var Widget = Widget || {};

(function(){
	Widget.Unit = Class.extend({
		
		// Constructor
		init: function(name, type) {
			this.name = name;
			this.type = type;
			this._id = null;
		},
		
		items: function() {
			return this._items;
		},
		
		add: function(item) {
			this._items.push(item);
		},
		update: function(index, item) {
			this._items[index] = item;
		},
		remove: function(index) {
			this._items.splice(index, 1);
		},
		stat: function(stat) {
			if (typeof(stat) != 'undefined') {
				this._saveStat(stat);
			} else {
				return this._loadStat();
			}
		},
		/*
		 * Internal methods 
		 */
		
		_onAdd: function() {
			this._saveStat(this._initStat());
		},
		_onRemove: function() {
			widget.setPreferenceForKey(null, 'unit-stat-' + this._id);
		},
		_onUpdate: function() {
		},
		_config: function() {
			return null;
		},
		_load: function(config) {
		},
		_saveStat: function(stat) {
			var statLiteral = '{\'correct\': ' + stat.correct + ', \'wrong\': ' + stat.wrong + '}';
			widget.setPreferenceForKey(statLiteral, 'unit-stat-' + this._id);
		},
		_loadStat: function(stat) {
			var stat = this._initStat();
			var statLiteral = widget.preferenceForKey('unit-stat-' + this._id);
			if (statLiteral != null && statLiteral.length > 0) {
				stat = eval("(" + statLiteral + ")");
			}
			return stat;
		},
		_initStat: function() {
			return {'correct': 0, 'wrong': 0};
		},
		equals: function(o) {
			return this.name == o.name; 
		}
		
	});
	Widget.Unit._unitRegistry = new Object();
	Widget.Unit.create = function(name, type) {
		return new Widget.Unit._unitRegistry[type](name);
	}
	
	Widget.Unit.Item = function(question, answers) {
		this.answers = answers;
		this.question = question;
	}
	
	Widget.MUnit = Widget.Unit.extend({
		
		// Constructor
		init: function(name) {
			this._super(name, Widget.MUnit._type);
			this._items = [];
		}
		
	});
	Widget.MUnit._type = "memory";
	Widget.MUnit._displayName = "Memory";
	//Widget.Unit._unitRegistry[Widget.MUnit._type] = Widget.MUnit;
	
	Widget.FileStoreUnit = Widget.Unit.extend({
		
		// Constructor
		init: function(name) {
			this._super(name, Widget.FileStoreUnit._type);
			this.__encode = 'UTF-8';
		},
		items: function() {
			if (typeof(this._items) == 'undefined' || this._items == null) {
				this._loadItems();
			}
			return this._items;
		},
		add: function(item) {
			this._super(item);
			this._saveItems();
		},
		update: function(index, item) {
			this._super(index, item);
			this._saveItems();
		},
		remove: function(index) {
			this._super(index);
			this._saveItems();
		},
		configure: function(file) {
			this._file = file;
			this._items = null;
		},
		file: function() {
			return this._file;
		},
		
		_onRemove: function() {
			this._super;
			if (this._file) {
				var file = opera.io.filesystem.mountPoints.resolve(this._file);
				if (file) {
					opera.io.filesystem.removeMountPoint(file);
				}
			}
		},
		_saveItems: function() {
			if (this._file) {
				
				var file = opera.io.filesystem.mountPoints.resolve(this._file);
				file.refresh();
				
				var s;
				try {
					s = file.open(file, 'w+');
					
					s.writeLine('<questions>', this.__encode);
					for (var i = 0; i < this._items.length; i++) {
						s.writeLine('<question>', this.__encode);
						s.writeLine('<text><![CDATA[' + this._items[i].question + ']]></text>', this.__encode);
						s.writeLine('<answers>', this.__encode);
						for (var j = 0; j < this._items[i].answers.length; j++) {
							s.writeLine('<answer><![CDATA[' + this._items[i].answers[j] + ']]></answer>', this.__encode);
						}
						s.writeLine('</answers>', this.__encode);
						s.writeLine('</question>', this.__encode);
					}
					s.writeLine('</questions>', this.__encode);
					
				} finally {
					if (s) {
						s.close();
					}
				}
				
			} else {
				throw new Error("File is not initialized");
			}
		},
		_loadItems: function() {
			
			if (this._file) {
				var file = opera.io.filesystem.mountPoints.resolve(this._file);
				file.refresh();
				
				var s;
				try {
					this._items = [];
					
					s = file.open(file, file.exists ? 'r' : 'w+');
					if (file.exists) {
						var xml = s.read(s.bytesAvailable, this.__encode);
						var xmlDoc = $.xmlDOM(xml);
						var items = [];
						
						xmlDoc.find('questions > question').each(function() {
							
							var question = $(this).find('text').text();
							var answers = [];
							
							$(this).find('answers > answer').each(function() {
								answers.push($(this).text());
							});
							
							items.push(new Widget.Unit.Item(question, answers));
						});
						this._items = items; 
					}
				} finally {
					if (s) {
						s.close();
					}
				}
			} else {
				throw new Error("File is not initialized");
			}
		},
		
		_config: function() {
			var config = new Object();
			config['file'] = this._file; 
			return config;
		},
		_load: function(config) {
			this._file = config['file'];
		}
	
	});
	Widget.FileStoreUnit._type = "fileStore";
	Widget.FileStoreUnit._displayName = "File";
	Widget.Unit._unitRegistry[Widget.FileStoreUnit._type] = Widget.FileStoreUnit;
	
	/**
	 * Unit manager provides methods for managing units 
	 */
	Widget.UnitManager = function() {
		
		var _units;
		
		function _init() {
			Widget.Utils.initializeSingleton(Widget.UnitManager, this);
		}
		
		this.add = function(unit) {
			_add(unit);
			_save_units();
		}
		
		// FIXME: refactor & test it
		this.remove = function(name) {
			_remove(name);
			_save_units();
		}
		
		this.get = function(name) {
			for (var i = 0; i < _units.length; i++) {
				if (_units[i].name == name) {
					return _units[i];
				}
			}
			return null;
		}
		
		this.update = function(unit) {
			for (var i = 0; i < _units.length; i++) {
				if (_units[i].name == name) {
					_update(i, unit);
				}
			}
		}
		
		this.list = function() {
			return _units;
		}
		
		this.types = function() {
			var unitTypes = new Array();
			for (type in Widget.Unit._unitRegistry) {
				unitTypes.push({'type': type, 'displayName': Widget.Unit._unitRegistry[type]._displayName});
			}
			return unitTypes;
		}
		
		this.contains = function(name) {
			return this.get(name) != null;
		}
		
		function _add(unit) {
			var lastId = 0;
			for (var i = 0; i < _units.length; i++) {
				if (lastId < _units[i]._id) {
					lastId = _units[i]._id;
				}
			}
			
			unit._id = lastId + 1; 
			unit._onAdd();
			_units.push(unit);
		}
		
		function _update(i, unit) {
			_units[i]._onUpdate();
			_units[i] = unit;
		}
		
		function _remove(name) {
			for (var i = 0; i < _units.length; i++) {
				var unit = _units[i];
				if (unit.name == name) {
					unit._onRemove();
					_units.splice(i, 1);
				}
			}
		}
		
		function _load() {
			_units = [];
			
			var unitStoreLiteral = widget.preferenceForKey(Widget.UnitManager_UNIT_STORE);
			
			if (!(unitStoreLiteral == null || unitStoreLiteral.length == 0)) {
				
				var unitStore = eval("(" + unitStoreLiteral + ")");
				for (key in unitStore.units) {
					
					// Instantiate the stored unit & configure it 
					var unit = Widget.Unit.create(unitStore.units[key].name, unitStore.units[key].type);
					unit._load(unitStore.units[key].config);
					unit._id = unitStore.units[key].id;
					_units.push(unit);
					
				}
			}
		}
		
		function _save_units() {
			var unitStoreLiteral = "{\"units\": [";
			
			for (var i = 0; i < _units.length; i++) {
				var unit = _units[i];
				
				unitStoreLiteral = unitStoreLiteral.concat("{ \'id\': " + unit._id + ", \"name\": \"" + unit.name + "\", \"type\": \"" + unit.type + "\", \"config\": {");

				// Save custom configuration parameters
				var unitConfigLiteral = '';
				var unitConfig = unit._config();
 				if (unitConfig && unitConfig.length != 0) {
 					for (key in unitConfig) {
 						
 						if (unitConfigLiteral.length > 0) {
 							unitConfigLiteral = unitConfigLiteral.concat(',');
 						}
 						
 						unitConfigLiteral = unitConfigLiteral.concat('\'' + key + '\': \'' + unitConfig[key]  + '\'');
 					}
 				}

 				unitStoreLiteral = unitStoreLiteral.concat(unitConfigLiteral);
				unitStoreLiteral = unitStoreLiteral.concat("}}");
				if (i + 1 < _units.length) {
					unitStoreLiteral = unitStoreLiteral.concat(", ");
				}
			}
			unitStoreLiteral = unitStoreLiteral.concat("]}");
			
			widget.setPreferenceForKey(unitStoreLiteral, Widget.UnitManager_UNIT_STORE);
		}
		
		// Initializer
		_init();
		_load();
	
	}
	
	//Static methods & methods
	Widget.UnitManager_UNIT_STORE = "unitStore";
	Widget.UnitManager.instance = function() {
		
		return Widget.Utils.singletonInstance(Widget.UnitManager, true);	
	
	}
})();